package io.jsen.meta.diff.feature.parser;

import io.jsen.meta.diff.exception.MetaDelValUndefinedException;
import io.jsen.meta.diff.feature.FieldControl;
import io.jsen.meta.diff.field.MetaFieldDefine;

import java.util.*;

/**
 * 这里定义三种容器类型(Map、List、Set)的删除，同时即使设置了自定义FieldControl，这个也是一个默认的兜底
 *
 * @author jsen
 * @date 2021/09/18
 **/
public class DefaultFieldControl implements FieldControl {

    @Override
    public <T> boolean isDelVal(MetaFieldDefine metaFieldDefine, T val) {
        if (val == null) {
            return false;
        }
        if (Collection.class.isAssignableFrom(metaFieldDefine.getCurrentFieldClass())) {
            return ((Collection<?>) val).size() == 0;
        }
        if (Map.class.isAssignableFrom(metaFieldDefine.getCurrentFieldClass())) {
            return ((Map<?, ?>) val).size() == 0;
        }
        return false;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getDelVal(MetaFieldDefine metaFieldDefine) {
        if (List.class.isAssignableFrom(metaFieldDefine.getCurrentFieldClass())) {
            return (T) new DelList<>();
        }
        if (Set.class.isAssignableFrom(metaFieldDefine.getCurrentFieldClass())) {
            return (T) new DelSet<>();
        }
        if (Map.class.isAssignableFrom(metaFieldDefine.getCurrentFieldClass())) {
            return (T) new DelMap<>();
        }
        throw new MetaDelValUndefinedException("未定义删除字段，但是Diff的数据有删除字段" + metaFieldDefine);
    }

    private static final class DelList<E> extends AbstractList<E> {

        @Override
        public E get(int index) {
            throw new IndexOutOfBoundsException("Index: " + index);
        }

        @Override
        public int size() {
            return 0;
        }
    }

    private static final class DelSet<E> extends AbstractSet<E> {

        @Override
        public Iterator<E> iterator() {
            return Collections.emptyIterator();
        }

        @Override
        public int size() {
            return 0;
        }
    }

    private static final class DelMap<K, V> extends AbstractMap<K, V> {
        @Override
        public Set<Entry<K, V>> entrySet() {
            return Collections.emptySet();
        }
    }
}
